using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using Deepcode.Flux.Core.Data;

namespace Deepcode.Flux.Core.Systems.Audit
{
	public class SystemEvents : BaseManager
	{
		#region Constructors
		public SystemEvents() : base() { }
		public SystemEvents(SqlConnection CurrentConnection) : base(CurrentConnection) { }
		public SystemEvents(SqlConnection CurrentConnection, SqlTransaction CurrentTransaction) : base(CurrentConnection, CurrentTransaction) { }
		#endregion
		#region Classes/App Classes/Type interrogations
		/// <summary>
		/// Return a list of all the event classes known on the system - ignoring event type
		/// </summary>
		/// <returns></returns>
		public string[] GetEventClasses()
		{
			List<string> list = new List<string>();
			DataTable MatchRows = new DataTable();

			EstablishConnection();
			SqlDataAdapter da = this.CreateDataAdapter("coreAuditGetEventClasses");
			da.Fill(MatchRows);
			ReleaseConnection();

			foreach (DataRow r in MatchRows.Rows)
				list.Add((string)r["Class"]);

			return list.ToArray();
		}
		/// <summary>
		/// Return a list of all the event classes known within a particular event type
		/// </summary>
		/// <param name="ForType"></param>
		/// <returns></returns>
		public string[] GetEventClassesInType(EventType ForType)
		{
			List<string> list = new List<string>();
			DataTable MatchRows = new DataTable();

			EstablishConnection();
			SqlDataAdapter da = this.CreateDataAdapter("coreAuditGetEventClassesInType");
			da.SelectCommand.Parameters.Add(SQLUtility.ParameterIn("@typeid", SqlDbType.Int, 4, (int)ForType));
			da.Fill(MatchRows);
			ReleaseConnection();

			foreach (DataRow r in MatchRows.Rows)
				list.Add((string)r["Class"]);

			return list.ToArray();
		}
		/// <summary>
		/// Returns a list of all the application classes within the system
		/// </summary>
		/// <param name="EventClass"></param>
		/// <returns></returns>
		public string[] GetAllApplicationClasses()
		{
			List<string> list = new List<string>();
			DataTable MatchRows = new DataTable();

			EstablishConnection();
			SqlDataAdapter da = this.CreateDataAdapter("coreAuditGetApplicationClasses");
			da.Fill(MatchRows);
			ReleaseConnection();

			foreach (DataRow r in MatchRows.Rows)
				list.Add((string)r["App"]);

			return list.ToArray();
		}
		/// <summary>
		/// Returns a list of all the application classes within a particular event class
		/// </summary>
		/// <param name="EventClass"></param>
		/// <returns></returns>
		public string[] GetApplicationClassesInEventClass(string EventClass)
		{
			List<string> list = new List<string>();
			DataTable MatchRows = new DataTable();

			EstablishConnection();
			SqlDataAdapter da = this.CreateDataAdapter("coreAuditGetApplicationClassesInEventClass");
			da.SelectCommand.Parameters.Add(SQLUtility.ParameterIn("@eventClass", SqlDbType.NVarChar, 50, EventClass));
			da.Fill(MatchRows);
			ReleaseConnection();

			foreach (DataRow r in MatchRows.Rows)
				list.Add((string)r["App"]);

			return list.ToArray();
		}
		/// <summary>
		/// Return a list of all the application classes within an event class for a particular type
		/// </summary>
		/// <param name="EventClass"></param>
		/// <param name="ForType"></param>
		/// <returns></returns>
		public string[] GetApplicationClassesInEventClassForType(string EventClass, EventType ForType)
		{
			List<string> list = new List<string>();
			DataTable MatchRows = new DataTable();

			EstablishConnection();
			SqlDataAdapter da = this.CreateDataAdapter("coreAuditGetApplicationClassesInEventClassForType");
			da.SelectCommand.Parameters.Add(SQLUtility.ParameterIn("@eventClass", SqlDbType.NVarChar, 50, EventClass));
			da.SelectCommand.Parameters.Add(SQLUtility.ParameterIn("@typeID", SqlDbType.Int, 4, (int)ForType));
			da.Fill(MatchRows);
			ReleaseConnection();

			foreach (DataRow r in MatchRows.Rows)
				list.Add((string)r["App"]);

			return list.ToArray();
		}
		#endregion
		#region Retreival of events
		/// <summary>
		/// Returns all of the actual event records for a particular class and appname
		/// </summary>
		/// <param name="EventClass"></param>
		/// <param name="AppName"></param>
		/// <returns></returns>
		public SystemEvent[] GetEventsForClassApp(string EventClass, string AppName)
		{
			if (EventClass == "") EventClass = "%";
			if (AppName == "") AppName = "%";

			List<SystemEvent> list = new List<SystemEvent>();
			DataTable MatchRows = new DataTable();

			EstablishConnection();
			SqlDataAdapter da = this.CreateDataAdapter("coreAuditGetEventsForClassApp");
			da.SelectCommand.Parameters.Add(SQLUtility.ParameterIn("@eventClass", SqlDbType.NVarChar, 50, EventClass));
			da.SelectCommand.Parameters.Add(SQLUtility.ParameterIn("@appName", SqlDbType.NVarChar, 200, AppName));
			da.Fill(MatchRows);
			ReleaseConnection();

			foreach (DataRow r in MatchRows.Rows)
				list.Add(new SystemEvent(r));

			return list.ToArray();
		}
		/// <summary>
		/// Returns all of the actual event records for a particular class and appname, but within a particular type
		/// </summary>
		/// <param name="EventClass"></param>
		/// <param name="AppName"></param>
		/// <param name="ForType"></param>
		/// <returns></returns>
		public SystemEvent[] GetEventsForClassAppAndType(string EventClass, string AppName, EventType ForType)
		{
			if (EventClass == "") EventClass = "%";
			if (AppName == "") AppName = "%";

			List<SystemEvent> list = new List<SystemEvent>();
			DataTable MatchRows = new DataTable();

			EstablishConnection();
			SqlDataAdapter da = this.CreateDataAdapter("coreAuditGetEventsForClassAppAndType");
			da.SelectCommand.Parameters.Add(SQLUtility.ParameterIn("@eventClass", SqlDbType.NVarChar, 50, EventClass));
			da.SelectCommand.Parameters.Add(SQLUtility.ParameterIn("@appName", SqlDbType.NVarChar, 200, AppName));
			da.SelectCommand.Parameters.Add(SQLUtility.ParameterIn("@typeid", SqlDbType.Int, 4, ForType));
			da.Fill(MatchRows);
			ReleaseConnection();

			foreach (DataRow r in MatchRows.Rows)
				list.Add(new SystemEvent(r));

			return list.ToArray();
		}
		/// <summary>
		/// Returns an array of system events matching the criteria specified
		/// </summary>
		/// <param name="searchText">The text to search for, or empty to search everything</param>
		/// <param name="UserID">The User ID to search for, or 0 to ignore (-1 = the system)</param>
		/// <param name="type">The type </param>
		/// <param name="minSeverity"></param>
		/// <param name="EventClass"></param>
		/// <param name="AppClass"></param>
		/// <param name="start"></param>
		/// <param name="end"></param>
		/// <returns></returns>
		public SystemEvent[] SearchEvents(string searchText, int UserID, SearchEventType type,
			EventSeverity minSeverity, string EventClass, string AppClass, DateTime start, DateTime end)
		{
			string finalSearchText = "%" + searchText + "%";
			DateTime finalEndDate = new System.DateTime( end.Year, end.Month, end.Day, 23, 59, 59 );

			
			List<SystemEvent> list = new List<SystemEvent>();
			DataTable MatchRows = new DataTable();

			EstablishConnection();
			SqlDataAdapter da = this.CreateDataAdapter("coreAuditSearchEvents");
			da.SelectCommand.Parameters.Add(SQLUtility.ParameterIn("@searchText", SqlDbType.NVarChar, 1024, finalSearchText));
			da.SelectCommand.Parameters.Add(SQLUtility.ParameterIn("@severity", SqlDbType.Int, 4, minSeverity));
			da.SelectCommand.Parameters.Add(SQLUtility.ParameterIn("@uid", SqlDbType.Int, 4, UserID));
			da.SelectCommand.Parameters.Add(SQLUtility.ParameterIn("@typeid", SqlDbType.Int, 4, type));
			da.SelectCommand.Parameters.Add(SQLUtility.ParameterIn("@class", SqlDbType.NVarChar, 50, EventClass));
			da.SelectCommand.Parameters.Add(SQLUtility.ParameterIn("@app", SqlDbType.NVarChar, 200, AppClass));
			da.SelectCommand.Parameters.Add(SQLUtility.ParameterIn("@start", SqlDbType.DateTime, 8, start));
			da.SelectCommand.Parameters.Add(SQLUtility.ParameterIn("@end", SqlDbType.DateTime, 8, finalEndDate));
			da.Fill(MatchRows);
			ReleaseConnection();

			foreach (DataRow r in MatchRows.Rows)
				list.Add(new SystemEvent(r));
			return list.ToArray();
		}
		#endregion
		#region Event Deletion
		/// <summary>
		/// Entirely clears the event log
		/// </summary>
		public void ClearLogs()
		{
			EstablishConnection();
			SqlCommand cmd = this.CreateSqlCommand("coreAuditClearLogs");
			cmd.ExecuteNonQuery();
			ReleaseConnection();
		}
		/// <summary>
		/// Clears events from the log earlier than the date/time specified
		/// </summary>
		/// <param name="EarlierThan"></param>
		public void ClearLogsBefore(DateTime EarlierThan)
		{
			EstablishConnection();
			SqlCommand cmd = this.CreateSqlCommand("coreAuditClearLogsBefore");
			cmd.Parameters.Add(SQLUtility.ParameterIn("@dtstamp", SqlDbType.DateTime, 8, EarlierThan));
			cmd.ExecuteNonQuery();
			ReleaseConnection();
		}
		#endregion
		#region Event Raising and Logging
		/// <summary>
		/// Raises an event and logs it to the system (provided configuration is set to log this event severity).
		/// </summary>
		/// <param name="severity"></param>
		/// <param name="type"></param>
		/// <param name="EventClass"></param>
		/// <param name="EventApp"></param>
		/// <param name="MessageFormat"></param>
		/// <param name="args"></param>
		public void Raise(EventSeverity severity, EventType type, int UserID, string EventClass, string EventApp, string MessageFormat, params object[] args)
		{
			bool bRaiseEvent = false;
			switch (severity)
			{
				case EventSeverity.Trace:
					if (SystemEventConfiguration.LogTrace) bRaiseEvent = true;
					break;
				case EventSeverity.Information:
					if (SystemEventConfiguration.LogInformation) bRaiseEvent = true;
					break;
				case EventSeverity.Important:
					if (SystemEventConfiguration.LogImportant) bRaiseEvent = true;
					break;
				case EventSeverity.Critical:
					if (SystemEventConfiguration.LogCritical) bRaiseEvent = true;
					break;
				case EventSeverity.Error:
					if (SystemEventConfiguration.LogError) bRaiseEvent = true;
					break;
			}
			if (bRaiseEvent)
			{
				EstablishConnection();
				SqlCommand cmd = this.CreateSqlCommand("coreAuditRaise");
				cmd.Parameters.Add(SQLUtility.ParameterIn("@uid", SqlDbType.Int, 4, UserID));
				cmd.Parameters.Add(SQLUtility.ParameterIn("@sid", SqlDbType.Int, 4, severity));
				cmd.Parameters.Add(SQLUtility.ParameterIn("@tid", SqlDbType.Int, 4, type));
				cmd.Parameters.Add(SQLUtility.ParameterIn("@class", SqlDbType.NVarChar, 50, EventClass));
				cmd.Parameters.Add(SQLUtility.ParameterIn("@app", SqlDbType.NVarChar, 200, EventApp));
				cmd.Parameters.Add(SQLUtility.ParameterIn("@message", SqlDbType.NVarChar, 1024, String.Format(MessageFormat, args)));
				cmd.ExecuteNonQuery();
				ReleaseConnection();
			}
		}
		/// <summary>
		/// Raises an event and logs it to the system (provided configuration is set to log this event severity).
		/// This override takes no type, and defaults to EventType.Application
		/// </summary>
		/// <param name="severity"></param>
		/// <param name="EventClass"></param>
		/// <param name="EventApp"></param>
		/// <param name="MessageFormat"></param>
		/// <param name="args"></param>
		public void Raise(EventSeverity severity, int UserID, string EventClass, string EventApp, string MessageFormat, params object[] args)
		{
			Raise(severity, EventType.Application, UserID, EventClass, EventApp, MessageFormat, args);
		}
		#endregion
	}
}
